/**
 * 
 */
package neptune.web.server.repository;

import it.robertobifulco.ias.RepositoryException;

import java.io.File;

import javax.xml.parsers.DocumentBuilderFactory;

import neptune.manager.builder.IPAddressRange;
import neptune.manager.model.topology.IPAddress;
import neptune.web.server.Debug;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * @author Roberto Bifulco [RobertoBifulco.it] [info@robertoBifulco.it]
 * @author Luigi Lorenzo Arpino [luigiarpino@yahoo.it]
 */
public class XMLConfigurationRepository implements ConfigurationRepository {

	private File xmlFile;

	private String rootDir;
	private String clusterFile = "cluster.xml";
	private String configurationFile = "configuration.xml";
	private String topologyDir = "topologies";
	private String templatesDir = "templates";
	private boolean debug;
	private String experimentDir;
	private IPAddressRange controlIPs = new IPAddressRange();
	private IPAddress expsSubnet;
	private IPAddress clusterSubnet;
	private String linkSubnet;

	private String vmTempRepDir;
	private String expsVMsDir;

	public XMLConfigurationRepository(String path) throws RepositoryException {
		if (!path.endsWith(File.separator)) {
			path += File.separator;
		}
		rootDir = path;

		xmlFile = new File(path + "configuration.xml");
		readRepositoryFile();
	}

	public boolean debugActive() {
		return debug;
	}

	public String getApplicationRootDirectoryName() {
		return rootDir;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeneptune.web.server.repository.ConfigurationRepository#
	 * getApplicationRootDirectory()
	 */
	public String getApplicationRootDirectoryPath() {
		return rootDir;
	}

	public IPAddress getBaseExperimentSubnet() {
		return expsSubnet;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * neptune.web.server.repository.ConfigurationRepository#getClusterFilePath
	 * ()
	 */
	public String getClusterFilePath() {
		return getApplicationRootDirectoryPath() + clusterFile;
	}

	public IPAddress getClusterSubnet() {
		return clusterSubnet;
	}

	public IPAddressRange getControlIPRange() {
		return controlIPs;
	}

	public String getExperimentsDirPath() {
		if (!experimentDir.endsWith(File.separator))
			experimentDir += File.separator;
		return rootDir + experimentDir;
	}

	public String getExperimentsVMsDir() {
		if (!expsVMsDir.endsWith(File.separator))
			expsVMsDir += File.separator;
		return expsVMsDir;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * neptune.web.server.repository.ConfigurationRepository#getLinkSubnet()
	 */
	public String getLinkSubnet() {
		return linkSubnet;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * neptune.web.server.repository.ConfigurationRepository#getPathTemplate()
	 */
	public String getTemplatePath() {
		return getApplicationRootDirectoryPath() + this.templatesDir;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeneptune.web.server.repository.ConfigurationRepository#
	 * getTopologyRootDirectoryName()
	 */
	public String getTopologyRootDirectoryName() {
		return topologyDir;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeneptune.web.server.repository.ConfigurationRepository#
	 * getTopologyRootDirectoryPath()
	 */
	public String getTopologyRootDirectoryPath() {
		String add = "";
		if (!topologyDir.endsWith(File.separator))
			add = File.separator;

		return getApplicationRootDirectoryPath() + topologyDir + add;
	}

	public String getVmTempRepDir() {
		return vmTempRepDir;
	}

	public synchronized void readRepositoryFile() throws RepositoryException {
		DocumentBuilderFactory docFactory = DocumentBuilderFactory
				.newInstance();
		docFactory.setValidating(false);

		try {
			Document doc = docFactory.newDocumentBuilder().parse(xmlFile);

			// cluster descriptor
			Element clusterDescrEl = (Element) doc.getElementsByTagName(
					"clusterDescriptor").item(0);
			clusterFile = clusterDescrEl.getAttribute("relativePath");

			// topology dir
			Element topDirEl = (Element) doc.getElementsByTagName(
					"topologiesDir").item(0);
			topologyDir = topDirEl.getAttribute("relativePath");

			// templates dir
			Element templateDirEl = (Element) doc.getElementsByTagName(
					"templatesDir").item(0);
			this.templatesDir = templateDirEl.getAttribute("relativePath");

			// experiments dir
			Element expDirEl = (Element) doc.getElementsByTagName(
					"experimentsDir").item(0);
			experimentDir = expDirEl.getAttribute("relativePath");

			// vmTemplates dir
			Element vmTempDirEl = (Element) doc.getElementsByTagName(
					"vmTemplatesDir").item(0);
			vmTempRepDir = vmTempDirEl.getAttribute("absolutePath");

			// experiment vms dir
			Element expsVmsDirEl = (Element) doc.getElementsByTagName(
					"experimentsVMsDir").item(0);
			expsVMsDir = expsVmsDirEl.getAttribute("absolutePath");

			// debug
			if (doc.getElementsByTagName("debug").getLength() > 0) {
				Element debugEl = (Element) doc.getElementsByTagName("debug")
						.item(0);
				debug = debugEl.getAttribute("active").equals("yes");
			}

			// control ip ranges
			NodeList ipRangeEls = doc.getElementsByTagName("ipRange");
			for (int i = 0; i < ipRangeEls.getLength(); i++) {
				Element ipRangeEl = (Element) ipRangeEls.item(i);
				IPAddress lower = new IPAddress(4, ipRangeEl
						.getAttribute("startIP"), ipRangeEl
						.getAttribute("netmask"));
				IPAddress upper = new IPAddress(4, ipRangeEl
						.getAttribute("endIP"), ipRangeEl
						.getAttribute("netmask"));
				controlIPs.addRange(lower, upper);
			}

			// experiment subnet base address
			if (doc.getElementsByTagName("experimentsSubnet").getLength() > 0) {
				Element subnetEl = (Element) doc.getElementsByTagName(
						"experimentsSubnet").item(0);
				expsSubnet = new IPAddress(4, subnetEl
						.getAttribute("baseAddress"), subnetEl
						.getAttribute("netmask"));
			}

			// cluster subnet
			if (doc.getElementsByTagName("clusterSubnet").getLength() > 0) {
				Element subnetEl = (Element) doc.getElementsByTagName(
						"clusterSubnet").item(0);
				clusterSubnet = new IPAddress(4, subnetEl
						.getAttribute("address"), subnetEl
						.getAttribute("netmask"));
			}

			// link subnet
			if (doc.getElementsByTagName("linkSubnet").getLength() > 0) {
				Element subnetEl = (Element) doc.getElementsByTagName(
						"linkSubnet").item(0);
				linkSubnet = subnetEl.getAttribute("netmask");
			}

		} catch (Exception e) {
			Debug.printTrace(e);
			throw new RepositoryException(e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeneptune.web.server.repository.ConfigurationRepository#
	 * getConfigurationFilePath()
	 */
	public String getConfigurationFilePath() {
		return getApplicationRootDirectoryPath() + configurationFile;
	}

}
